package com.haojiang.mh.widget.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.haojiang.mh.R;
import com.haojiang.mh.service.entity.SleepCycleChartBean;
import com.haojiang.mh.service.entity.SleepDurationBean;
import com.haojiang.mh.utils.SizeUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 双Y轴+分段矩形
 * 当前用在《周报--睡眠周期分析》
 */
public class WeekSleepCycleChartView extends View {

    private TextPaint textPaint;//文字画笔
    private Paint coordinatePaint, columnPaint;//坐标刻度、柱子画笔
    private int width, height, defaultWidth, defaultHeight;//当前View宽高、默认宽高度
    private float xItemWidth, yItemHeight;//X轴间隔块宽度、Y轴间隔块高度
    //柱子高度、Y轴宽度、Y轴文字高度、X轴文字高度、X轴高度、坐标轴间隔、绘制高度
    private int columnHeight, yAxisWidth, yAxisTextHeight, xAxisTextHeight, xAxisHeight, axisPadding, drawHeight;
    //深睡眠、浅睡眠、REM、清醒、工作日、周末 颜色值
    private int deepColor, lightColor, remColor, awakeColor, workDayColor, weekendColor;
    private String[] yAxisLeft, yAxisRight;//y轴左右坐标对应文本
    private int yAxisTextSize, xAxisTextSize;//Y轴、X轴文本字体大小
    private List<SleepCycleChartBean> beanList;//数据集
    private RectF rectF = new RectF();//矩形
    private int hourNum = 18;

    public WeekSleepCycleChartView(Context context) {
        this(context, null);
    }

    public WeekSleepCycleChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WeekSleepCycleChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        columnHeight = SizeUtil.dp2px(context, 20);
        yAxisWidth = SizeUtil.dp2px(context, 30);
        yAxisTextHeight = SizeUtil.dp2px(context, 20);
        xAxisTextHeight = SizeUtil.dp2px(context, 30);
        xAxisHeight = SizeUtil.dp2px(context, 3);
        axisPadding = SizeUtil.dp2px(context, 10);
        drawHeight = SizeUtil.dp2px(context, 170);

        defaultWidth = SizeUtil.dp2px(context, 340);
        defaultHeight = drawHeight + axisPadding + xAxisHeight + xAxisTextHeight;

        workDayColor = getResources().getColor(R.color.white_half);
        weekendColor = getResources().getColor(R.color.purple_3);
        deepColor = getResources().getColor(R.color.purple_4);
        lightColor = getResources().getColor(R.color.purple_3);
        remColor = getResources().getColor(R.color.purple_2);
        awakeColor = getResources().getColor(R.color.grey_3);

        yAxisTextSize = SizeUtil.sp2px(context, 12);
        xAxisTextSize = SizeUtil.sp2px(context, 10);

        yAxisLeft = new String[]{"20", "21", "22", "23", "24", "25", "26"};
        yAxisRight = getResources().getStringArray(R.array.chinaWeekDayArray);

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

        coordinatePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coordinatePaint.setStyle(Paint.Style.FILL);
        coordinatePaint.setColor(workDayColor);

        columnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        columnPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (beanList == null || beanList.isEmpty()) return;

        xItemWidth = (float) (width - yAxisWidth * 2 - axisPadding * 2) / hourNum;
        yItemHeight = (float) drawHeight / yAxisLeft.length;

        /* 绘制X轴 */
        drawXAxis(canvas);

        /* 绘制Y轴 */
        drawYAxis(canvas);

        /* 绘制分段矩形 */
        drawColumn(canvas);
    }

    /**
     * 绘制X轴
     */
    private void drawXAxis(Canvas canvas) {
        textPaint.setTextSize(xAxisTextSize);
        textPaint.setTextAlign(Paint.Align.CENTER);
        for (int i = 0; i <= hourNum; i++) {
            if (i % 2 != 0) continue;
            float xItemPosition = yAxisWidth + axisPadding + xItemWidth * i;
            canvas.drawLine(
                    xItemPosition,
                    height - xAxisTextHeight - xAxisHeight,
                    xItemPosition,
                    height - xAxisTextHeight,
                    coordinatePaint
            );
            textPaint.setColor(workDayColor);
            canvas.drawText(
                    i + "h",
                    xItemPosition,
                    SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制Y轴
     */
    private void drawYAxis(Canvas canvas) {
        textPaint.setTextSize(yAxisTextSize);
        for (int i = 0; i < yAxisLeft.length; i++) {
            float yItemMidPosition = yItemHeight * i + yItemHeight * 0.5f;
            textPaint.setColor((i == 5 || i == 6) ? weekendColor : workDayColor);
            textPaint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(
                    yAxisLeft[i],
                    yAxisWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, yItemMidPosition + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
            canvas.drawCircle(yAxisWidth, yItemMidPosition, 5, coordinatePaint);
            textPaint.setTextAlign(Paint.Align.LEFT);
            canvas.drawText(
                    yAxisRight[i],
                    width - yAxisWidth,
                    SizeUtil.getBaseLine(textPaint, yItemMidPosition + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制分段矩形
     */
    private void drawColumn(Canvas canvas) {
        int totalMinute = hourNum * 60;
        int drawWidth = width - yAxisWidth * 2 - axisPadding * 2;
        for (int i = 0; i < beanList.size(); i++) {
            SleepCycleChartBean bean = beanList.get(i);
            if (bean == null || bean.getLine() == null || bean.getLine().isNull()) continue;
            SleepDurationBean sdb = bean.getLine();
            //深睡眠
            float deepRight = yAxisWidth + axisPadding + sdb.getDeep_duration_minute() * drawWidth / totalMinute;
            rectF.set(
                    yAxisWidth + axisPadding,
                    yItemHeight * i + yItemHeight * 0.5f - columnHeight * 0.5f,
                    deepRight,
                    yItemHeight * i + yItemHeight * 0.5f + columnHeight * 0.5f
            );
            columnPaint.setColor(deepColor);
            canvas.drawRect(rectF, columnPaint);
            //浅睡眠
            float lightRight = deepRight + sdb.getLight_duration_minute() * drawWidth * 1.0f / totalMinute;
            rectF.set(
                    deepRight,
                    yItemHeight * i + yItemHeight * 0.5f - columnHeight * 0.5f,
                    lightRight,
                    yItemHeight * i + yItemHeight * 0.5f + columnHeight * 0.5f
            );
            columnPaint.setColor(lightColor);
            canvas.drawRect(rectF, columnPaint);
            //REM
            float remRight = lightRight + sdb.getRem_duration_minute() * drawWidth * 1.0f / totalMinute;
            rectF.set(
                    lightRight,
                    yItemHeight * i + yItemHeight * 0.5f - columnHeight * 0.5f,
                    remRight,
                    yItemHeight * i + yItemHeight * 0.5f + columnHeight * 0.5f
            );
            columnPaint.setColor(remColor);
            canvas.drawRect(rectF, columnPaint);
            //清醒
            float awakeRight = remRight + sdb.getAwake_duration_minute() * drawWidth * 1.0f / totalMinute;
            if (awakeRight > (yAxisWidth + axisPadding + drawWidth)) {
                awakeRight = yAxisWidth + axisPadding + drawWidth;
            }
            rectF.set(
                    remRight,
                    yItemHeight * i + yItemHeight * 0.5f - columnHeight * 0.5f,
                    awakeRight,
                    yItemHeight * i + yItemHeight * 0.5f + columnHeight * 0.5f
            );
            columnPaint.setColor(awakeColor);
            canvas.drawRect(rectF, columnPaint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                getMeasuredLength(widthMeasureSpec, true),
                getMeasuredLength(heightMeasureSpec, false)
        );
    }

    private int getMeasuredLength(int length, boolean isWidth) {
        int specMode = MeasureSpec.getMode(length);
        int specSize = MeasureSpec.getSize(length);
        int size;
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (specMode == MeasureSpec.EXACTLY) {
            size = specSize;
        } else if (specMode == MeasureSpec.UNSPECIFIED) {
            size = isWidth ? defaultWidth : defaultHeight;
        } else {
            size = isWidth ? padding + defaultWidth : padding + defaultHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                size = Math.min(size, specSize);
            }
        }
        return size;
    }

    public void setChartData(List<SleepCycleChartBean> data) {
        if (beanList == null) beanList = new ArrayList<>();
        beanList.clear();
        int max = 0;
        if (data != null && !data.isEmpty()) {
            beanList.addAll(data);
            for (int i = 0; i < beanList.size(); i++) {
                SleepCycleChartBean bean = beanList.get(i);
                SleepDurationBean line = bean.getLine();
                max = Math.max(max, line.getDeep_duration_minute() + line.getAwake_duration_minute() + line.getLight_duration_minute() + line.getRem_duration_minute());
                yAxisLeft[i] = bean.getDay();
                if (max > 60 * 18) {
                    break;
                }
            }
        }
        if (max > 60 * 18) {
            hourNum = 24;
        } else {
            hourNum = 18;
        }
        invalidate();
    }
}

